package com.pallass.common.jpa.criteria;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Join;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;

import org.apache.commons.lang3.StringUtils;

import com.pallass.common.jpa.domain.SpecificationItem;

public enum OperatorType {

	INTEUQAL {
		@Override
		public Predicate combine(Root<?> root, CriteriaBuilder criteriaBuilder, SpecificationItem item) {
			if (StringUtils.isBlank(item.getSubClassProperty())) {
				return criteriaBuilder.equal(root.get(item.getKey()).as(Integer.class), item.getValue());
			} else {
				Join<?, ?> join = generateJoin(root, item);
				return criteriaBuilder.equal(join.get(item.getKey()).as(Integer.class), item.getValue());
			}
		}

	},

	INTNOTEUQAL {
		@Override
		public Predicate combine(Root<?> root, CriteriaBuilder criteriaBuilder, SpecificationItem item) {
			if (StringUtils.isBlank(item.getSubClassProperty())) {
				return criteriaBuilder.notEqual(root.get(item.getKey()).as(Integer.class), item.getValue());
			} else {
				Join<?, ?> join = generateJoin(root, item);
				return criteriaBuilder.notEqual(join.get(item.getKey()).as(Integer.class), item.getValue());
			}
		}
	},
	LIKE {
		@Override
		public Predicate combine(Root<?> root, CriteriaBuilder criteriaBuilder, SpecificationItem item) {
			// parse object
			if (StringUtils.isBlank(item.getSubClassProperty())) {
				return criteriaBuilder.like(root.get(item.getKey()).as(String.class), "%" + item.getValue().toString().trim() + "%");
			} else {
				Join<?, ?> join = generateJoin(root, item);
				return criteriaBuilder.like(join.get(item.getKey()).as(String.class), "%" + item.getValue().toString().trim() + "%");
			}
		}
	};

	private static Join<?, ?> generateJoin(Root<?> root, SpecificationItem item) {
		Join<?, ?> join = null;
		String[] sps = StringUtils.split(item.getSubClassProperty(), ".");
		if (sps != null && sps.length > 0) {
			join = root.join(sps[0]);
			for (int i = 1; i < sps.length; i++) {
				join = join.join(sps[i]);
			}
		}
		return join;
	}

	public abstract Predicate combine(Root<?> root, CriteriaBuilder criteriaBuilder, SpecificationItem item);

}
